package gui;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import shared.PlayerPosition;
import deck.Card;
import deck.Suit;
import deck.Value;

@SuppressWarnings("serial")
public class TableImage extends JPanel implements MouseListener {
	public static enum SelectionMode {NONE, SINGLE, MULTIPLE};

	private static final int BORDER = 10;
	private HandImage north, south, east, west;
	private Card northPlayed, southPlayed, eastPlayed, westPlayed;
	private Point northPoint, southPoint, eastPoint, westPoint;
	private SelectionMode selectionMode;
	private JButton mainButton;
	private Action prevAct = null;

	public TableImage(List<Card> north, List<Card> south, List<Card> east, List<Card> west) {
		setBackground(Color.GREEN);
		setSelectionMode(SelectionMode.NONE);
		this.north = new HandImage(north);
		this.south = new HandImage(south);
		this.east = new HandImage(east);
		this.west = new HandImage(west);

		this.northPlayed = new Card();
		this.southPlayed = new Card();
		this.westPlayed = new Card();
		this.eastPlayed = new Card();
		this.addMouseListener(this);
		
		mainButton = new JButton("INVISIBLE");
		mainButton.addActionListener(new AbstractAction() {
			public void actionPerformed(ActionEvent arg0) {
//				mainButton.setEnabled(false);
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				mainButton.setVisible(false);
				TableImage.this.repaint();
			}
		});
		this.setLayout(new GridBagLayout());
		this.add(mainButton);
		mainButton.setVisible(false);
		mainButton.setEnabled(false);
	}
	
	public void tradeCards(Action act) {
		mainButton.setText("Trade!");
		setSelectionMode(SelectionMode.MULTIPLE);
		mainButton.setEnabled(true);
		mainButton.setVisible(true);
		mainButton.removeActionListener(prevAct);
		mainButton.addActionListener(act);
		prevAct = act;
	}
	
	public void playCard(Action act){
		mainButton.setText("Play!");
		setSelectionMode(SelectionMode.SINGLE);
		mainButton.setEnabled(false);
		mainButton.setVisible(true);
		mainButton.removeActionListener(prevAct);
		mainButton.addActionListener(act);
		prevAct = act;
	}
	
	public void showStartGameButton(Action act){
		mainButton.setText("Start Game");
		setSelectionMode(SelectionMode.NONE);
		mainButton.setEnabled(true);
		mainButton.setVisible(true);
		mainButton.removeActionListener(prevAct);
		mainButton.addActionListener(act);
		prevAct = act;
	}

	public int getBid(List<Integer> bids){
		Vector<String> options = new Vector<String>();
		for(Integer bid : bids){
			if(bid.equals(0)){
				options.add("Pass");
			} else if (bid.equals(5)){
				options.add("Smudge");
			}else {
				options.add(bid.toString());
			}
		}
		Object choice = null;
		while(choice == null){
			choice = JOptionPane.showInputDialog(this, "Select Bid", "BID", 
					JOptionPane.QUESTION_MESSAGE, null, options.toArray(), 
					options.firstElement());
		}
		return bids.get(options.indexOf(choice));
	}

	public Suit getTrump(){
		Object choice = null;
		while(choice == null){
			choice = JOptionPane.showInputDialog(this, "Select Bid", "BID", 
					JOptionPane.QUESTION_MESSAGE, null, new Object[]{
					Suit.SPADES, Suit.CLUBS, Suit.DIAMONDS, Suit.HEARTS}, 
					Suit.SPADES);
		}
		return (Suit) choice;
	}

	public void setHandleForPosition(PlayerPosition pos, String name){
		getHand(pos).setHandle(name);
	}

	public void setSelectionMode(SelectionMode mode){
		this.selectionMode = mode;
	}

	public SelectionMode getSelectionMode(){
		return selectionMode;
	}

	public void playCard(PlayerPosition pos, Card card){
		getCard(pos).setCard(card);
	}

	public List<Card> getSelectedCards(PlayerPosition pos){
		List<Card> ret = new ArrayList<Card>();
		for(Card card : getHand(pos).getCards()){
			if(card.isSelected())
				ret.add(card);
		}
		return ret;
	}

	public Card getSelectedCard(PlayerPosition pos){
		for(Card card : getHand(pos).getCards()){
			if(card.isSelected())
				return card;
		}
		return null;
	}

	private HandImage getHand(PlayerPosition pos){
		HandImage hand = null;
		switch (pos){
		case EAST:
			hand = east;
			break;
		case NORTH:
			hand = north;
			break;
		case SOUTH:
			hand = south;
			break;
		case WEST:
			hand = west;
			break;
		}
		return hand;
	}

	private Card getCard(PlayerPosition pos){
		Card card = null;
		switch (pos){
		case EAST:
			card = eastPlayed;
			break;
		case NORTH:
			card = northPlayed;
			break;
		case SOUTH:
			card = southPlayed;
			break;
		case WEST:
			card = westPlayed;
			break;
		}
		return card;
	}

	public void setPlayableCards(PlayerPosition pos, List<Card> cards){
		HandImage hand = getHand(pos);
		hand.setPlayableCards(cards);
		repaint();
	}

	public void setSelectedCards(PlayerPosition pos, List<Card> cards){
		HandImage hand = getHand(pos);
		hand.setSelectedCards(cards);
		repaint();
	}

	public void replaceHand(PlayerPosition pos, List<Card> newHand){
		HandImage hand = getHand(pos);
		if(hand != null)
			hand.replaceHand(newHand);
		this.repaint();
	}

	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		Font nameFont = new Font(g.getFont().getName(), Font.BOLD, 18);
		Color nameColor = Color.RED;

		Graphics g2 = g.create();
		north.recalculateSize(g2);
		northPoint = new Point((this.getWidth() - north.getSize().width) / 2, BORDER);
		g2.translate(northPoint.x, northPoint.y);
		north.draw(g2);
		g2.setFont(nameFont);
		g2.setColor(nameColor);
		g2.drawString(north.getHandle(), 0, north.getSize().height + 18 + BORDER);

		g2 = g.create();
		west.recalculateSize(g2);
		westPoint = new Point(BORDER, (int) ((this.getHeight() - west.getSize().getHeight()) / 2));
		g2.translate(westPoint.x, westPoint.y);
		west.draw(g2);
		g2.setFont(nameFont);
		g2.setColor(nameColor);
		g2.drawString(west.getHandle(), 0, -BORDER);

		g2 = g.create();
		east.recalculateSize(g2);
		eastPoint = new Point(this.getWidth() - BORDER - east.getSize().width, 
				(this.getHeight() - east.getSize().height) / 2);
		g2.translate(eastPoint.x, eastPoint.y);
		east.draw(g2);
		g2.setFont(nameFont);
		g2.setColor(nameColor);
		g2.drawString(east.getHandle(), 0, -BORDER);

		g2 = g.create();
		south.recalculateSize(g2);
		southPoint = new Point(((int) (this.getWidth() - south.getSize().getWidth()) / 2), 
				(int) (this.getHeight() - BORDER - south.getSize().getHeight()));
		g2.translate(southPoint.x, southPoint.y);
		south.draw(g2);
		g2.setFont(nameFont);
		g2.setColor(nameColor);
		g2.drawString(south.getHandle(), 0, -BORDER);

		if(northPlayed.isVisible()){
			Image card = CardImages.getImage(northPlayed.getSuit(), northPlayed.getValue());
			g.drawImage(card, (this.getWidth() - card.getWidth(null)) / 2, 
					(int) ((this.getHeight() - card.getHeight(null) * 3) / 2), null);
		}
		if(southPlayed.isVisible()){
			Image card = CardImages.getImage(southPlayed.getSuit(), southPlayed.getValue());
			g.drawImage(card, (this.getWidth() - card.getWidth(null)) / 2, 
					(int) ((this.getHeight() + card.getHeight(null)) / 2), null);
		}
		if(westPlayed.isVisible()){
			Image card = CardImages.getImage(westPlayed.getSuit(), westPlayed.getValue());
			g.drawImage(card, (this.getWidth() - card.getWidth(null) * 3) / 2, 
					(this.getHeight() - card.getHeight(null)) / 2, null);
		}
		if(eastPlayed.isVisible()){
			Image card = CardImages.getImage(eastPlayed.getSuit(), eastPlayed.getValue());
			g.drawImage(card, (this.getWidth() + card.getWidth(null))/ 2, 
					(this.getHeight() - card.getHeight(null)) / 2, null);
		}
		
	}

	public static void main(String[] args) {
		JFrame frame = new JFrame();
		frame.setSize(500, 500);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		List<Card> north = new ArrayList<Card>();
		north.add(new Card(Suit.SPADES, Value.ACE));
		north.add(new Card(Suit.DIAMONDS, Value.QUEEN));
		north.add(new Card(Suit.CLUBS, Value.NINE));
		north.add(new Card(Suit.CLUBS, Value.FIVE));
		north.add(new Card(Suit.HEARTS, Value.FIVE));
		north.add(new Card(Suit.HEARTS, Value.TWO));

		List<Card> oth = new ArrayList<Card>();
		oth.add(new Card(Suit.BLUE, Value.ACE));
		oth.add(new Card(Suit.BLUE, Value.ACE));
		oth.add(new Card(Suit.BLUE, Value.ACE));
		oth.add(new Card(Suit.BLUE, Value.ACE));
		oth.add(new Card(Suit.BLUE, Value.ACE));
		oth.add(new Card(Suit.BLUE, Value.ACE));

		TableImage ti = new TableImage(oth, north, oth, oth);
		ti.playCard(PlayerPosition.NORTH, new Card(Suit.DIAMONDS, Value.KING));
		ti.playCard(PlayerPosition.SOUTH, new Card(Suit.DIAMONDS, Value.QUEEN));
		ti.playCard(PlayerPosition.EAST, new Card(Suit.DIAMONDS, Value.JACK));
		ti.playCard(PlayerPosition.WEST, new Card(Suit.DIAMONDS, Value.TWO));

		ti.setPlayableCards(PlayerPosition.SOUTH, north.subList(2, 6));
		ti.setSelectedCards(PlayerPosition.SOUTH, north.subList(2, 3));

		ti.setSelectionMode(SelectionMode.SINGLE);

		frame.add(ti);
		frame.setVisible(true);
		
		ti.playCard(null);
	}

	public void mouseClicked(MouseEvent e) {}
	public void mouseEntered(MouseEvent e) {}
	public void mouseExited(MouseEvent e) {}

	public void mousePressed(MouseEvent e) {
		switch(selectionMode){
		case NONE:
			return;
		case SINGLE:
			north.setMultiSelect(false);
			south.setMultiSelect(false);
			east.setMultiSelect(false);
			west.setMultiSelect(false);
			break;
		case MULTIPLE:
			north.setMultiSelect(true);
			south.setMultiSelect(true);
			east.setMultiSelect(true);
			west.setMultiSelect(true);
			break;
		}
		Rectangle northRect = new Rectangle(northPoint);
		northRect.setSize(north.getSize());
		if(northRect.contains(e.getPoint())){
			for(int i = 0; i < north.getCards().size(); i++){
				if((i + 1) * HandImage.STACKED_CARD_WIDTH > e.getX() - northRect.x){
					if(north.getCards().get(i).isPlayable()){
						north.setSelectedCard(north.getCards().get(i));
						mainButton.setEnabled(true);
					}
					break;
				}
				if(i + 1 == north.getCards().size() && north.getCards().get(i).isPlayable()){
					north.setSelectedCard(north.getCards().get(i));
					mainButton.setEnabled(true);
				}
			}
		}

		Rectangle southRect = new Rectangle(southPoint);
		southRect.setSize(south.getSize());
		if(southRect.contains(e.getPoint())){
			for(int i = 0; i < south.getCards().size(); i++){
				if((i + 1) * HandImage.STACKED_CARD_WIDTH > e.getX() - southRect.x){
					if(south.getCards().get(i).isPlayable()){
						south.setSelectedCard(south.getCards().get(i));
						mainButton.setEnabled(true);
					}
					break;
				}
				if(i + 1 == south.getCards().size() && south.getCards().get(i).isPlayable()){
					south.setSelectedCard(south.getCards().get(i));
					mainButton.setEnabled(true);
				}
			}
		}

		Rectangle eastRect = new Rectangle(eastPoint);
		eastRect.setSize(east.getSize());
		if(eastRect.contains(e.getPoint())){
			for(int i = 0; i < east.getCards().size(); i++){
				if((i + 1) * HandImage.STACKED_CARD_WIDTH > e.getX() - eastRect.x){
					if(east.getCards().get(i).isPlayable()){
						east.setSelectedCard(east.getCards().get(i));
						mainButton.setEnabled(true);
					}
					break;
				}
				if(i + 1 == east.getCards().size() && east.getCards().get(i).isPlayable()){
					east.setSelectedCard(east.getCards().get(i));
					mainButton.setEnabled(true);
				}
			}
		}

		Rectangle westRect = new Rectangle(westPoint);
		westRect.setSize(west.getSize());
		if(westRect.contains(e.getPoint())){
			for(int i = 0; i < west.getCards().size(); i++){
				if((i + 1) * HandImage.STACKED_CARD_WIDTH > e.getX() - westRect.x){
					if(west.getCards().get(i).isPlayable()){
						west.setSelectedCard(west.getCards().get(i));
						mainButton.setEnabled(true);
					}
					break;
				}
				if(i + 1 == west.getCards().size() && west.getCards().get(i).isPlayable()){
					west.setSelectedCard(west.getCards().get(i));
					mainButton.setEnabled(true);
				}
			}
		}
		
		repaint();
	}

	public void mouseReleased(MouseEvent e) {}
}
